import pytest
from unittest.mock import patch, MagicMock
import requests

# 模拟API响应数据
MOCK_SUCCESS_RESPONSE = {
    "Response": {
        "Price": {
            "InstancePrice": {
                "OriginalPrice": 120.00,
                "DiscountPrice": 1.20
            }
        },
        "RequestId": "e2e81b08-d747-455e-b27a-aecc5acafdba"
    }
}

# 新增专用模拟响应
MOCK_INVALID_PERIOD_RESPONSE = {
    "Response": {
        "Error": {
            "Code": "InvalidPeriod",
            "Message": "续费时长无效，必须为1-36个月"
        }
    }
}

MOCK_DRY_RUN_RESPONSE = {
    "Response": {
        "Error": {
            "Code": "DryRunOperation",
            "Message": "DryRun模式成功，实际未执行"
        }
    }
}

MOCK_MISSING_PARAMS_RESPONSE = {
    "Response": {
        "Error": {
            "Code": "MissingParameter",
            "Message": "缺少必填参数InstanceIds"
        }
    }
}


class TestCvmRenewInstances:
    @pytest.fixture(autouse=True)
    def setup(self):
        self.base_url = "https://cvm.tencentcloudapi.com"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": "Bearer TEST_TOKEN"
        }
        self.base_params = {
            "Action": "InquiryPriceRenewInstances",
            "Version": "2017-03-12",
            "Region": "ap-guangzhou",
            "InstanceIds": ["ins-2zvpghhc"],
            "InstanceChargePrepaid": {"Period": 1},
            "DryRun": False
        }

    @pytest.fixture
    def mock_response(self, mocker):
        """创建通用响应模拟对象"""
        mock_resp = MagicMock()
        mock_resp.raise_for_status.return_value = None
        mocker.patch("requests.post", return_value=mock_resp)
        return mock_resp

    def send_request(self, params):
        """实际请求发送函数"""
        try:
            response = requests.post(
                self.base_url,
                headers=self.headers,
                json=params
            )
            response.raise_for_status()
            return response.json()
        except requests.RequestException as e:
            return {"Error": str(e)}

    def test_valid_request(self, mock_response):
        mock_response.json.return_value = MOCK_SUCCESS_RESPONSE
        response = self.send_request(self.base_params)

        assert response["Response"]["Price"]["InstancePrice"]["OriginalPrice"] == 120.00
        assert response["Response"]["RequestId"] == "e2e81b08-d747-455e-b27a-aecc5acafdba"

    def test_invalid_period(self, mock_response):
        mock_response.json.return_value = MOCK_INVALID_PERIOD_RESPONSE
        params = self.base_params.copy()
        params["InstanceChargePrepaid"]["Period"] = 0

        response = self.send_request(params)
        assert response["Response"]["Error"]["Code"] == "InvalidPeriod"

    def test_dry_run_mode(self, mock_response):
        mock_response.json.return_value = MOCK_DRY_RUN_RESPONSE
        params = self.base_params.copy()
        params["DryRun"] = True

        response = self.send_request(params)
        assert response["Response"]["Error"]["Code"] == "DryRunOperation"

    def test_missing_instance_ids(self, mock_response):
        mock_response.json.return_value = MOCK_MISSING_PARAMS_RESPONSE
        params = self.base_params.copy()
        del params["InstanceIds"]

        response = self.send_request(params)
        assert response["Response"]["Error"]["Code"] == "MissingParameter"


# 执行命令
if __name__ == "__main__":
    pytest.main(["-s", "--html=report.html", __file__])